package com.ywd.platform.netty.jt080.po;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import lombok.Data;

/**
 * JT808 协议常量及工具类
 * 包含协议标准定义、消息ID、消息体属性、位标志等常量
 */
@Data
public class JT808Protocol {

    // ================ 协议基础常量 ================
    /** 协议头标识 (0x7E) */
    public static final byte HEADER_FLAG = 0x7E;
    /** 转义字符 (0x7D) */
    public static final byte ESCAPE_FLAG = 0x7D;
    /** 协议默认字符集 (GBK) */
    public static final String DEFAULT_CHARSET = "GBK";
    /** 终端手机号长度 */
    public static final int PHONE_NUMBER_LENGTH = 6;

    // ================ 消息ID定义 ================
    // 终端上行消息
    /**
     * 终端注册消息 (0x0100)
     * - 功能：终端设备在连接平台时发送的首条消息，用于向平台注册终端身份信息
     * - 方向：终端 → 平台
     * - 内容包含：
     *   • 终端手机号（设备SIM卡号）
     *   • 终端制造商ID
     *   • 终端型号
     *   • 终端ID
     *   • 车牌颜色/号码
     * - 十进制：256
     */
    public static final int MSG_ID_TERMINAL_REGISTER = 0x0100;

    /**
     * 终端鉴权消息 (0x0102)
     * - 功能：终端向平台提交鉴权信息（如设备密码或令牌），建立安全连接
     * - 方向：终端 → 平台
     * - 触发条件：
     *   • 终端注册成功后平台要求鉴权
     *   • 连接保持期间定时重新鉴权
     * - 十进制：258
     */
    public static final int MSG_ID_TERMINAL_AUTH = 0x0102;

    /**
     * 位置信息上报消息 (0x0200)
     * - 功能：终端向平台上报车辆的实时位置和状态信息
     * - 方向：终端 → 平台
     * - 上报频率：支持定时/定距/事件触发上报
     * - 内容包含：
     *   • GNSS定位信息（经纬度、海拔、速度）
     *   • 行驶记录仪数据（里程、速度）
     *   • 车辆状态（ACC开/关、油路状态）
     *   • 报警标志（超速报警、紧急报警）
     * - 十进制：512
     */
    public static final int MSG_ID_LOCATION_REPORT = 0x0200;

    /**
     * 终端心跳消息 (0x0002)
     * - 功能：终端定期发送给平台以保持TCP连接存活的空消息
     * - 方向：终端 → 平台
     * - 发送间隔：默认60秒（可配置）
     * - 作用：
     *   • 维持TCP长连接
     *   • 检测终端在线状态
     * - 十进制：2
     */
    public static final int MSG_ID_HEARTBEAT = 0x0002;

    // 查询终端参数
    public static final int MSG_ID_TERMINAL_PARAM_QUERY = 0x0104;

    //事件报告
    public static final int MSG_ID_EVENT_REPORT = 0x0301;

    //驾驶员身份信息采集
    public static final int MSG_ID_DRIVER_INFO = 0x0704;

    // 平台下行消息
    //========================================================
    public static final int MSG_ID_SERVER_COMMON_RESP = 0x8001;          // 平台通用应答
    public static final int MSG_ID_SERVER_REGISTER_RESP = 0x8100;        // 注册应答
    public static final int MSG_ID_SERVER_SET_PARAM = 0x8103;            // 设置终端参数
    public static final int MSG_ID_SERVER_SELECT_PARAM = 0x8104;         // 查询终端参数

    // ================ 消息体属性位定义 ================
    /** 消息体长度掩码 (0x3FF) */
    public static final int MSG_BODY_LENGTH_MASK = 0x3FF;
    /** 是否有分包 (0x2000) */
    public static final int MSG_BODY_PACKAGE_FLAG = 0x2000;
    /** 数据加密方式掩码 (0x1C00) */
    public static final int MSG_BODY_ENCRYPT_MASK = 0x1C00;

    // ================ 位置信息状态位定义 ================
    /** 0x00000001:  ACC开关状态 */
    public static final int STATUS_ACC_ON = 0x00000001;
    /** 0x00000002:  定位状态 */
    public static final int STATUS_LOCATED = 0x00000002;
    /** 0x00000004:  南纬标志 */
    public static final int STATUS_SOUTH_LAT = 0x00000004;
    /** 0x00000008:  西经标志 */
    public static final int STATUS_WEST_LNG = 0x00000008;

    // ================ 报警标志位定义 ================
    /** 0x00000001:  紧急报警 */
    public static final int ALARM_EMERGENCY = 0x00000001;
    /** 0x00000002:  超速报警 */
    public static final int ALARM_OVERSPEED = 0x00000002;
    /** 0x00000004:  疲劳驾驶 */
    public static final int ALARM_FATIGUE = 0x00000004;

    // ================ 协议工具方法 ================

    /**
     * 计算校验码 (XOR累加)
     * @param data 包含消息头、消息体的完整数据（不包含头尾标识）
     */
    public static byte calculateCheckCode(byte[] data) {
        byte checkCode = 0;
        for (byte b : data) {
            checkCode ^= b;
        }
        return checkCode;
    }

    /**
     * 转义处理 (用于发送数据)
     * JT808协议要求对0x7E、0x7D进行转义
     * @param raw 原始数据
     * @return 转义后的数据
     */
    public static byte[] escape(byte[] raw) {
        ByteBuf buf = Unpooled.buffer();
        try {
            for (byte b : raw) {
                if (b == HEADER_FLAG) {
                    buf.writeByte(ESCAPE_FLAG);
                    buf.writeByte(0x02);
                } else if (b == ESCAPE_FLAG) {
                    buf.writeByte(ESCAPE_FLAG);
                    buf.writeByte(0x01);
                } else {
                    buf.writeByte(b);
                }
            }
            byte[] result = new byte[buf.readableBytes()];
            buf.readBytes(result);
            return result;
        } finally {
            buf.release();
        }
    }

    /**
     * 反转义处理 (用于接收数据)
     * @param escaped 转义后的数据
     * @return 原始数据
     */
    public static byte[] unescape(byte[] escaped) {
        ByteBuf buf = Unpooled.buffer();
        try {
            for (int i = 0; i < escaped.length; i++) {
                byte b = escaped[i];
                if (b == ESCAPE_FLAG) {
                    byte next = escaped[++i];
                    if (next == 0x01) {
                        buf.writeByte(ESCAPE_FLAG);
                    } else if (next == 0x02) {
                        buf.writeByte(HEADER_FLAG);
                    }
                } else {
                    buf.writeByte(b);
                }
            }
            byte[] result = new byte[buf.readableBytes()];
            buf.readBytes(result);
            return result;
        } finally {
            buf.release();
        }
    }

    /**
     * 格式化终端手机号 (6字节BCD码转字符串)
     */
    public static String formatPhoneNumber(byte[] bcdBytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bcdBytes) {
            sb.append(String.format("%02X", b));
        }
        return sb.toString();
    }

    /**
     * 格式化时间 (BCD码转字符串 yyyy-MM-dd HH:mm:ss)
     */
    public static String formatTime(byte[] bcdTime) {
        return String.format("20%02x-%02x-%02x %02x:%02x:%02x",
                bcdTime[0], bcdTime[1], bcdTime[2],
                bcdTime[3], bcdTime[4], bcdTime[5]);
    }

    /**
     * 检查状态位是否设置
     * @param status 状态值
     * @param flag 要检查的标志位
     */
    public static boolean isStatusSet(int status, int flag) {
        return (status & flag) == flag;
    }

}
